﻿namespace OpenQ.Infrastructure.DomainRepositoryExtensions
{
    using System;
    using System.Diagnostics;
    using System.Security.Permissions;

    using Repository;
    using DomainObjects;
    
    //[StrongNameIdentityPermissionAttribute(SecurityAction.Demand, PublicKey = "0024000004800000940000000602000000240000525341310004000001000100639f96fb72d686c38d8485948b84d5b8fda415c75d005dba502010e7bb5ea007f5933bc6ad986bfa4a768c338be5db87101efd6de5f5a394c3f1994e0e435e0e46f27e4154d3d0cb6c5cd2fda41131999227775c2a50f80200668c82d69546c98618f1065ea5b2f632776fc203949f3f61c07c3860d6d47cf486e9e1df003ab1")]
    public static class StoryExtension
    {
        [DebuggerStepThrough]
        public static int GetViewCount(this IStory forStory)
        {
            Check.Argument.IsNotNull(forStory, "forStory");
            return GetCount<IStoryViewRepository>(forStory.Id);
        }

        [DebuggerStepThrough]
        public static int GetVoteCount(this IStory forStory)
        {
            Check.Argument.IsNotNull(forStory, "forStory");
            return GetCount<IVoteRepository>(forStory.Id);
        }

        [DebuggerStepThrough]
        public static int GetMarkAsSpamCount(this IStory forStory)
        {
            Check.Argument.IsNotNull(forStory, "forStory");
            return GetCount<IMarkAsSpamRepository>(forStory.Id);
        }

        [DebuggerStepThrough]
        public static int GetCommentCount(this IStory forStory)
        {
            Check.Argument.IsNotNull(forStory, "forStory");
            return GetCount<ICommentRepository>(forStory.Id);
        }

        [DebuggerStepThrough]
        public static int GetSubscriberCount(this IStory forStory)
        {
            Check.Argument.IsNotNull(forStory, "forStory");
            return GetCount<ICommentSubscribtionRepository>(forStory.Id);
        }

        [DebuggerStepThrough]
        private static int GetCount<T>(Guid storyId) where T : class, ICountByStoryRepository
        {
            return IoC.Resolve<T>().CountByStory(storyId);
        }

        [DebuggerStepThrough]
        public static IStoryView AddView(this IStory forStory, DateTime at, string fromIpAddress)
        {
            Check.Argument.IsNotNull(forStory, "forStory");
            Check.Argument.IsNotInvalidDate(at, "at");
            Check.Argument.IsNotEmpty(fromIpAddress, "fromIpAddress");

            var view = IoC.Resolve<IDomainObjectFactory>().CreateStoryView(forStory, at, fromIpAddress);
            IoC.Resolve<IStoryViewRepository>().Add(view);
            
            return view;
        }

        [DebuggerStepThrough]
        public static IVote AddVote(this IStory forStory, DateTime at, IUser byUser, string fromIpAddress)
        {
            Check.Argument.IsNotNull(forStory, "forStory");
            Check.Argument.IsNotInFuture(at, "at");
            Check.Argument.IsNotNull(byUser, "byUser");
            Check.Argument.IsNotEmpty(fromIpAddress, "fromIpAddress");

            var vote = IoC.Resolve<IDomainObjectFactory>().CreateStoryVote(forStory, at, byUser, fromIpAddress);
            IoC.Resolve<IVoteRepository>().Add(vote);

            return vote;
        }

        [DebuggerStepThrough]
        public static void RemoveVote(this IStory fromStory, IVote vote)
        {
            Check.Argument.IsNotNull(fromStory, "fromStory");
            Check.Argument.IsNotNull(vote, "vote");
            IoC.Resolve<IVoteRepository>().Remove(vote);            
        }

        [DebuggerStepThrough]
        public static IVote GetVote(this IStory forStory,IUser byUser)
        {
            Check.Argument.IsNotNull(forStory, "forStory");
            Check.Argument.IsNotNull(byUser, "byUser");
            return IoC.Resolve<IVoteRepository>().FindById(forStory.Id, byUser.Id);
        }

        [DebuggerStepThrough]
        public static IMarkAsSpam MarkSpam(this IStory forStory, DateTime at, IUser byUser, string fromIpAddress)
        {
            Check.Argument.IsNotNull(forStory, "forStory");
            Check.Argument.IsNotInFuture(at, "at");
            Check.Argument.IsNotNull(byUser, "byUser");
            Check.Argument.IsNotEmpty(fromIpAddress, "fromIpAddress");

            var spamStory = IoC.Resolve<IDomainObjectFactory>().CreateMarkAsSpam(forStory, at, byUser, fromIpAddress);
            IoC.Resolve<IMarkAsSpamRepository>().Add(spamStory);
            
            return spamStory;
        }

        [DebuggerStepThrough]
        public static void UnmarkSpam(this IStory forStory, IMarkAsSpam spam)
        {
            Check.Argument.IsNotNull(forStory, "forStory");
            Check.Argument.IsNotNull(spam, "spam");
            IoC.Resolve<IMarkAsSpamRepository>().Remove(spam);
        }

        [DebuggerStepThrough]
        public static IMarkAsSpam GetMarkAsSpam(this IStory forStory, IUser byUser)
        {
            Check.Argument.IsNotNull(forStory, "forStory");
            Check.Argument.IsNotNull(byUser, "byUser");
            return IoC.Resolve<IMarkAsSpamRepository>().FindById(forStory.Id, byUser.Id);
        }

        [DebuggerStepThrough]
        public static IComment AddComment(this IStory forStory, string content, DateTime at, IUser byUser, string fromIpAddress)
        {
            var comment = IoC.Resolve<IDomainObjectFactory>().CreateComment(forStory, content, at, byUser, fromIpAddress);
            IoC.Resolve<ICommentRepository>().Add(comment);
            return comment;
        }

        [DebuggerStepThrough]
        public static IComment GetComment(this IStory forStory, Guid commentId)
        {
            Check.Argument.IsNotNull(forStory, "forStory");
            Check.Argument.IsNotEmpty(commentId, "commentId");
            return IoC.Resolve<ICommentRepository>().FindById(forStory.Id, commentId);
        }

        [DebuggerStepThrough]
        public static void RemoveComment(this IStory forStory, IComment comment)
        {
            Check.Argument.IsNotNull(forStory, "forStory");
            Check.Argument.IsNotNull(comment, "comment");
            IoC.Resolve<ICommentRepository>().Remove(comment);
        }

        [DebuggerStepThrough]
        public static ICommentSubscribtion GetCommentSubscribtion(this IStory forStory, IUser theUser)
        {
            Check.Argument.IsNotNull(forStory, "forStory");
            Check.Argument.IsNotNull(theUser, "theUser");
            return IoC.Resolve<ICommentSubscribtionRepository>().FindById(forStory.Id, theUser.Id);
        }

        [DebuggerStepThrough]
        public static ICommentSubscribtion AddCommentSubscribtion(this IStory forStory, IUser byUser)
        {
            Check.Argument.IsNotNull(forStory, "forStory");
            Check.Argument.IsNotNull(byUser, "byUser");

            var subscribtion = forStory.GetCommentSubscribtion(byUser);

            if (subscribtion == null)
            {
                subscribtion = IoC.Resolve<IDomainObjectFactory>().CreateCommentSubscribtion(forStory, byUser);
                IoC.Resolve<ICommentSubscribtionRepository>().Add(subscribtion);
            }
            return subscribtion;
        }

        [DebuggerStepThrough]
        public static ICommentSubscribtion RemoveCommentSubscribtion(this IStory forStory, IUser byUser)
        {
            Check.Argument.IsNotNull(forStory, "forStory");
            Check.Argument.IsNotNull(byUser, "byUser");

            var subscribtion = forStory.GetCommentSubscribtion(byUser);

            if (subscribtion != null)
            {
                IoC.Resolve<ICommentSubscribtionRepository>().Remove(subscribtion);
            }
            return subscribtion;
        }

    }
}
